import { createApp } from 'vue'
import { addClass, removeClass } from './dom.js'

// bug点: 注意这个 className 类名不需要加 .
const relativeCls = 'g-relative'

export default function createLoadingLikeDirective (Comp) {

  return {
    mounted (el, binding) {
      const app = createApp(Comp)
      console.log(Comp)   // 组件的名称 ?
      // 创建一个动态 div 实例, 这是为什么?
      const instance = app.mount(document.createElement('div'))
      // 将 instance 缓存起来
      // bug点, 一个组件或元素绑定多个指令会出现 el.instance 对象被覆盖问题!!!
      // el.instance = instance

      // 使用下面解决方案, 区分开一个组件上的不同指令
      const name = Comp.name
      if (!el[name]) {
        el[name] = {}
      }
      el[name].instance = instance

      // 优化: 设置title
      const title = binding.arg
      // 不等于空的一种判断方式
      if (typeof title !== 'undefined') {
        instance.setTitle(title)
      }

      if (binding.value) {
        append(el)
      }
    },
    /**
     * 一旦组件和子级被更新, 调用这个钩子
     * @param el        表示当前指令所绑定到的那个DOM元素
     * @param binding   v-loading="loading" -> loading值传递给 binding 参数, 使用binding.value拿到真正的值
     */
    updated (el, binding) {
      // 优化: 设置title
      // v-loading:[loadingText]="loading"   bind.arg = loadingText变量的值
      const title = binding.arg
      const name = Comp.name
      // 不等于空的一种判断方式
      if (typeof title !== 'undefined') {
        el[name].instance.setTitle(title)
      }

      // 更新方法时, 可以拿到oldValue
      if (binding.value !== binding.oldValue) {
        binding.value ? append(el) : remove(el)
      }
    }
  }

  function append (el, name) {
    // 优化 动态给el添加一个相对定位的样式
    const style = getComputedStyle(el)
    if (['absolute', 'fixed', 'relative'].indexOf(style.position) === -1) {
      addClass(el, relativeCls)
    }
    el.appendChild(el[name].instance.$el)
  }

  function remove (el, name) {
    removeClass(el, relativeCls)
    el.removeChild(el[name].instance.$el)
  }
}




